//
// LBXDownLoadItem.m
// LBXDownLoad
//
// Created by lbxia on 2021/4/20
//
//
    

#import "LBXDownLoadItem.h"
#import <CommonCrypto/CommonDigest.h>
#import <LBXFileHelper.h>


@interface LBXDownLoadItem()<NSCoding>
@property (nonatomic, copy) NSString *localFilePath;
@property (nonatomic, copy) NSString *remoteURLMd5;
@property (nonatomic, strong) NSDate *preDate;
@end

@implementation LBXDownLoadItem

- (void)setStatus:(LBXDownloadStatus)status
{
    if (_status != status) {
        _status = status;
        
        if (status == LBXDownloadStatus_Completed) {
            
            self.downSize = self.fileSize;
            
            [self deleteItem];
        }
        
        if (_onStatusChanged) {
            _onStatusChanged(self);
        }
        [self storeItem];
    }
}

- (void)setDownSize:(int64_t)downSize
{
    if (_downSize < downSize && _fileSize > 0) {
        _downSize = downSize;
        
        if (_onProgressChanged && _downSize < _fileSize ) {
            
            if (!_preDate) {
                self.preDate = [NSDate date];
                _onProgressChanged(self);
            }
            else
            {
                NSDate *nowDate = [NSDate date];
                if ( _downSize == _fileSize ) {
                    _onProgressChanged(self);
                    self.preDate = nil;
                }
                else if ( [nowDate timeIntervalSinceDate:self.preDate] > 1 ) {
                    _onProgressChanged(self);
                    self.preDate = nowDate;
                }
            }
        }
    }
}

- (void)setResumeData:(NSData *)resumeData
{
    _resumeData = resumeData;
    
    [self storeItem];
}

+ (NSString*)itemStoreDir
{
    static NSString *itemDir = nil;
    
    if (!itemDir) {
        itemDir = [[LBXFileHelper documentDir]stringByAppendingPathComponent:@"LBXDownLoad"];
        itemDir = [itemDir stringByAppendingPathComponent:@"ItemInfo"];
        [LBXFileHelper createFolder:itemDir];
    }
    return itemDir;
}


+ (NSString*)fileStoreDir
{
    static NSString *fileDir = nil;
    
    if (!fileDir) {
        fileDir = [[LBXFileHelper documentDir]stringByAppendingPathComponent:@"LBXDownLoad"];
        fileDir = [fileDir stringByAppendingPathComponent:@"LBXDownLoadFile"];
        [LBXFileHelper createFolder:fileDir];
    }
    return fileDir;
}

+ (NSString*)md5:(NSData*)data
{
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5( data.bytes, (CC_LONG)data.length, result ); // This is the md5 call
    return [NSString stringWithFormat:
            @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
            result[0], result[1], result[2], result[3],
            result[4], result[5], result[6], result[7],
            result[8], result[9], result[10], result[11],
            result[12], result[13], result[14], result[15]
            ];
}

- (NSString*)remoteURLMd5
{
    if (!_remoteURLMd5) {
        
        if (_remoteURL) {
            _remoteURLMd5 = [LBXDownLoadItem md5:[_remoteURL dataUsingEncoding:NSUTF8StringEncoding]];
        }
    }
    return _remoteURLMd5;
}

- (NSString*)taskDescription
{
    if (!_taskDescription) {
        _taskDescription = self.remoteURLMd5;
        
        if (_taskDescription) {
            
            NSString *suffix = [self.remoteURL pathExtension];
            if (suffix) {
                _taskDescription  = [NSString stringWithFormat:@"%@.%@",_taskDescription,suffix];
            }
        }
    }
    return _taskDescription;
}

- (NSString*)localFilePath
{
    if (!_localFilePath) {
        if (self.taskDescription) {
            _localFilePath = [[LBXDownLoadItem fileStoreDir] stringByAppendingPathComponent:self.taskDescription];
        }
    }
    return _localFilePath;
}

- (void)storeItem
{
    if (!self.remoteURLMd5) {
        return;
    }
    @synchronized (self) {
        NSString *itemPath = [LBXDownLoadItem itemStoreDir];
        itemPath = [itemPath stringByAppendingPathComponent:self.remoteURLMd5];
        NSData *item = [NSKeyedArchiver archivedDataWithRootObject:self];
        if (item) {
            [LBXFileHelper deleteFolderPath:itemPath];
            [item writeToFile:itemPath atomically:YES];
        }
    }
}

- (void)deleteItem
{
    @synchronized (self) {
        NSString *itemPath = [LBXDownLoadItem itemStoreDir];
        itemPath = [itemPath stringByAppendingPathComponent:self.remoteURLMd5];
        [LBXFileHelper deleteFolderPath:itemPath];
    }
}

+ (LBXDownLoadItem*)itemFromSandBoxWithRemoteURL:(NSString*)remoteURL
{
    if (!remoteURL) {
        return nil;
    }
    NSString *remoteURLMd5  = [LBXDownLoadItem md5:[remoteURL dataUsingEncoding:NSUTF8StringEncoding]];
    NSString *itemPath = [LBXDownLoadItem itemStoreDir];
    itemPath = [itemPath stringByAppendingPathComponent:remoteURLMd5];
    NSData *data = [NSData dataWithContentsOfFile:itemPath];
    if (data) {
        LBXDownLoadItem *item = [NSKeyedUnarchiver unarchiveObjectWithData:data];
        return item;
    }
    return nil;
}

- (BOOL)fileCacheExist
{
    if (self.localFilePath) {
        return [LBXFileHelper fileExistsAtPath:self.localFilePath];
    }
    return NO;
}

+ (BOOL)fileCacheExistWithRemoteURL:(NSString*)remoteURL
{
    NSString *suffix = [remoteURL pathExtension];
    NSString *localFilePath = nil;
    NSString *remoteURLMd5 = [LBXDownLoadItem md5:[remoteURL dataUsingEncoding:NSUTF8StringEncoding] ];
    if (suffix) {
        localFilePath = [[LBXDownLoadItem fileStoreDir] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@",remoteURLMd5,suffix]];
    }
    else
    {
        localFilePath = [[LBXDownLoadItem fileStoreDir] stringByAppendingPathComponent:remoteURLMd5];
    }
    
    return [LBXFileHelper fileExistsAtPath:localFilePath];
}

+ (NSString*)localfilePathWithRemoteURL:(NSString*)remoteURL
{
    NSString *suffix = [remoteURL pathExtension];
    NSString *localFilePath = nil;
    NSString *remoteURLMd5 = [LBXDownLoadItem md5:[remoteURL dataUsingEncoding:NSUTF8StringEncoding]];
    if (suffix) {
        localFilePath = [[LBXDownLoadItem fileStoreDir] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@",remoteURLMd5,suffix]];
    }
    else
    {
        localFilePath = [[LBXDownLoadItem fileStoreDir] stringByAppendingPathComponent:remoteURLMd5];
    }
    
    BOOL exist = [LBXFileHelper fileExistsAtPath:localFilePath];
    
    if (exist) {
        return  localFilePath;
    }
    
    return nil;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.remoteURL forKey:@"remoteURL"];
    
    [aCoder encodeInt64:self.fileSize forKey:@"fileSize"];
    [aCoder encodeInt64:self.downSize forKey:@"downSize"];
    [aCoder encodeInt32:(int32_t)self.status forKey:@"status"];

    [aCoder encodeInt64:self.taskIdentifier forKey:@"taskIdentifier"];
    [aCoder encodeObject:self.taskDescription forKey:@"taskDescription"];
    [aCoder encodeInt32:(int32_t)self.priorityLevel forKey:@"priorityLevel"];

    if ( self.resumeData && self.resumeData.length > 0 )
    {
        [aCoder encodeObject:self.resumeData forKey:@"resumeData"];
    }
}

- (id)initWithCoder:(NSCoder *)aCoder
{
    self = [super init];
    if (self)
    {
        self.remoteURL = [aCoder decodeObjectForKey:@"remoteURL"];
        self.fileSize = [aCoder decodeInt64ForKey:@"fileSize"];
        self.downSize = [aCoder decodeInt64ForKey:@"downSize"];

        self.status =  [aCoder decodeInt32ForKey:@"status"];
        self.taskIdentifier =  [aCoder decodeInt64ForKey:@"taskIdentifier"];
        self.taskDescription = [aCoder decodeObjectForKey:@"taskDescription"];
        self.priorityLevel = [aCoder decodeInt32ForKey:@"priorityLevel"];

        self.resumeData = [aCoder decodeObjectForKey:@"resumeData"];
    }
    return self;
}

@end

@implementation LBXDownLoadProgress
- (instancetype)init
{
    if (self = [super init]) {
        self.preWrittenTime = [NSDate date];
    }
    return self;
}
@end
